#include "paket_parse.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <cjson/cJSON.h>

// Chunk starts here
struct string 
{
  char *ptr;
  size_t len;
};
void
init_string(struct string *s) 
{
  s->len = 0;
  s->ptr = malloc(s->len+1);
  if (s->ptr == NULL) {
    fprintf(stderr, "malloc() failed\n");
    exit(EXIT_FAILURE);
  }
  s->ptr[0] = '\0';
}
size_t
writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
{
  size_t new_len = s->len + size*nmemb;
  s->ptr = realloc(s->ptr, new_len+1);
  if (s->ptr == NULL) {
    fprintf(stderr, "realloc() failed\n");
    exit(EXIT_FAILURE);
  }
  memcpy(s->ptr+s->len, ptr, size*nmemb);
  s->ptr[new_len] = '\0';
  s->len = new_len;

  return size*nmemb;
}
// Ends here
/* All this does is let me take the output of cURL and put it into
 * a more normal string that cJSON can parse.
 * I don't entirely understand it but it works.
 */

void
parse(int plook, int pexac, char package[])
{
	CURL *curl;
	CURLcode res;

	/* I hate JSON
	 * This part just declares all the variables
	 * that are needed to parse the JSON returned
	 * by the aur searching tool, provided by
	 * archlinux's website.
	 */
	cJSON* jName        = NULL;
	cJSON* jDescription = NULL;
	cJSON* jDepends     = NULL;
	cJSON* jLicense     = NULL;
	cJSON* jOutOfDate   = NULL;
	cJSON* jVersion     = NULL;

	char search[100] = "https://aur.archlinux.org/rpc/?v=5&type=search&by=name-desc&arg=";
	char exact[85]   = "https://aur.archlinux.org/rpc/?v=5&type=info&arg=";

	int i;

	struct string s;
	init_string(&s);

	// AUR only accepts search of 2 characters or more
	int length = strlen(package);
	if (length < 2) {
		printf("error: search term (%s) too short\n", package);
		exit(2);
	} else if (length >= 35) {
		printf("error: search term (%s) too long\n", package);
		exit(2);
	}

	curl = curl_easy_init();
	if (!curl) {
		printf("error: curl init failed\n");
		exit(1);
	}

	if (pexac) {
		// append "package" string to the "search" string
		strcat(exact, package);
		curl_easy_setopt(curl, CURLOPT_URL, exact);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
		curl_easy_perform(curl);

		cJSON *raw_json = cJSON_Parse(s.ptr);
		cJSON *results = cJSON_GetObjectItem(raw_json,"results");

		for (i = 0; i < cJSON_GetArraySize(results) ; i++) {
			cJSON * subitem = cJSON_GetArrayItem(results, i);

			jName = cJSON_GetObjectItem(subitem, "Name");
			jVersion = cJSON_GetObjectItem(subitem, "Version");
			jDescription = cJSON_GetObjectItem(subitem, "Description");
			jDepends = cJSON_GetObjectItem(subitem, "Depends");
			jLicense = cJSON_GetObjectItem(subitem, "License");
			jOutOfDate = cJSON_GetObjectItem(subitem, "OutOfDate");

			// the ++ and strlen()-1 removes the first and last character
			char *Name = cJSON_Print(jName);
			Name++;
			Name[strlen(Name)-1] = 0;

			char *Version = cJSON_Print(jVersion);
			Version++;
			Version[strlen(Version)-1] = 0;

			char *Description = cJSON_Print(jDescription);
			Description++;
			Description[strlen(Description)-1] = 0;

			char *Depends = cJSON_Print(jDepends);

			char *License = cJSON_Print(jLicense);
			License++;
			License[strlen(License)-1] = 0;

			char *OutOfDate = cJSON_Print(jOutOfDate);

			printf("\033[1;37mName:         \033[0;37m%s\n", Name);
			// change output for out of date packages
			if (OutOfDate[0] != 'n')
				printf("\033[1;37mVersion:      \033[0;31m%s (Out of date!)\n", Version);
			else
				printf("\033[1;37mVersion:      \033[0;37m%s\n", Version);
			printf("\033[1;37mDescription:  \033[0;37m%s\n", Description);
			printf("\033[1;37mLicense:      \033[0;37m%s\n", License);
			// prevent segfault if no dependencies
			if (Depends)
				printf("\033[1;37mDependencies:\n    \033[1;30m%s\n", Depends);
		}
	} else if (plook) {
		// append "package" string to the "search" string
		strcat(search, package);
		curl_easy_setopt(curl, CURLOPT_URL, search);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
		curl_easy_perform(curl);

		cJSON *raw_json = cJSON_Parse(s.ptr);
		cJSON *results = cJSON_GetObjectItem(raw_json,"results");

		for (i = 0; i < cJSON_GetArraySize(results) ; i++) {
			cJSON * subitem = cJSON_GetArrayItem(results, i);

			jName = cJSON_GetObjectItem(subitem, "Name");
			jVersion = cJSON_GetObjectItem(subitem, "Version");
			jDescription = cJSON_GetObjectItem(subitem, "Description");
			jOutOfDate = cJSON_GetObjectItem(subitem, "OutOfDate");

			char *Name = cJSON_Print(jName);
			Name++;
			Name[strlen(Name)-1] = 0;

			char *Version = cJSON_Print(jVersion);
			Version++;
			Version[strlen(Version)-1] = 0;

			char *Description = cJSON_Print(jDescription);
			Description++;
			Description[strlen(Description)-1] = 0;

			char *OutOfDate = cJSON_Print(jOutOfDate);

			// change output for out of date packages
			if (OutOfDate[0] != 'n') {
				printf("\033[1;37m%s \033[1;31m(%s - flagged!)\033[0;37m\n", Name, Version);
				printf("    %s\n", Description);
			}
			if (OutOfDate[0] == 'n') {
				printf("\033[1;37m%s \033[1;32m(%s)\033[0;37m\n", Name, Version);
				printf("    %s\n", Description);
			}
		}
	}

	free(s.ptr);
	curl_easy_cleanup(curl);
}
